<template>
  <DataTree v-if="_adapter" :adapter="_adapter" @confirm="updateChartData" />
  <div class="container" ref="ganttContainer">
    <div ref="toolTip" v-if="tipValue" class="tool-tip" :style="tipStyle">
      {{ tipValue }}
    </div>
    <div class="left-board">
      <div class="project-top-left-corner">
        <div class="title-bg progress-title-bg"></div>
        <div class="title-bg task-title-bg"></div>
        <div class="header-title progress-title">进度</div>
        <div class="header-title task-title">任务</div>
      </div>
      <div
        class="item-cell"
        :key="item.key"
        :style="item.style"
        :data-id="item.key"
        v-for="item in _options"
      >
        <div
          v-if="item.isChild"
          style="width: 2px; height: 20px; background-color: blue"
        ></div>
        {{ item.name }}
        <el-button
          v-if="item.canExpand"
          type="primary"
          size="small"
          @click="(event) => addSubProject(item, event)"
          >{{ item.showFlag === "open" ? "展开" : "收起" }}</el-button
        >
      </div>
    </div>
    <div class="right-board">
      <svg :id="domId" class="svg-container" />
    </div>
  </div>
</template>
<script setup>
import * as d3 from "d3";
import { nextTick, onMounted, ref, toRaw } from "vue";
import { initChart } from "./gantt.chart.js";
import { projects } from "./data.mjs";
import DataAdapter from "./gantt.adapter";
import eventHub from "./utils/eventHub.js";
import DataTree from "./data.tree.vue";

const toolTip = ref(null),
  ganttContainer = ref(null),
  tipValue = ref(""),
  tipStyle = ref({});
//###########
const self = {};
const _options = ref([]),
  _adapter = ref(null);
const domId = "svg-canvas-id";
let _cells = null;
onMounted(init);

function init() {
  addHubs();
  let svg = document.getElementById(domId);
  if (!svg) return;
  let { width, height } = svg.getBoundingClientRect();
  //   console.log("[%s,%s]", width, height);

  _adapter.value = new DataAdapter();
  _adapter.value.data = projects;

  self.chart = initChart(svg, {
    width,
    height,
    updateProjects,
    yZoomInited,
    yZoomUpdated,
    yMaxLevel: 3,
  });

  setTimeout(() => {
    updateChartData();
  }, 700);

  function yZoomUpdated(scale) {
    if (!_cells) return;
    // console.log("_cells", _cells);
    let bandWidth = scale.bandwidth();
    _cells.each(function (d) {
      let selection = d3.select(this);
      let id = this.dataset.id;
      let top = scale(id);
      selection.style("height", `${bandWidth}px`).style("top", `${top}px`);
    });
  }

  function yZoomInited(zoom) {
    let leftBoard = d3.select(".left-board");
    leftBoard.call(zoom);
  }

  function updateProjects(scale) {
    let domains = scale.domain();
    let height = scale.bandwidth();
    let cells = _adapter.value.getDisplayCells(domains);
    let marginLeft = 10;
    _options.value = cells.map((cell) => {
      let { key, level, canExpand, data, showFlag } = cell;
      let top = scale(key);
      let left = marginLeft * (level - 1);
      return {
        key,
        name: data.label || data.name || data.id,
        canExpand,
        showFlag,
        isChild: level > 1,
        style: {
          height: `${height}px`,
          top: `${top}px`,
          paddingLeft: `${left}px`,
          //   transform: `translate(0,${ty}px)`,
        },
      };
    });

    nextTick(() => {
      _cells = d3.selectAll(".item-cell");
    });
  }
}

function updateChartData() {
  let adapter = _adapter.value;
  let options = adapter.options;
  let plans = adapter.getPlans(options);
  let timeZone = adapter.timeZone;
  //   console.log("plans", plans);
  self.chart.update(options, plans, timeZone);
}

function addSubProject(item, event) {
  event.stopPropagation();
  event.preventDefault();
  let adapter = _adapter.value;
  const { key, showFlag } = item;
  if (showFlag === "open") {
    adapter.openKey(key);
  }

  if (showFlag === "close") {
    adapter.closeKey(key);
  }
  updateChartData();
}

function addHubs() {
  let names = [
    {
      name: "mouseenter",
      callback: (tipKey, clientX, clientY) => {
        let container = ganttContainer.value;
        if (!container) return;
        let bouding = container.getBoundingClientRect();
        let top = clientY - bouding.y;
        let left = clientX - bouding.x;

        tipValue.value = tipKey;
        tipStyle.value = {
          left: left + "px",
          top: top + "px",
        };
      },
    },
    {
      name: "mousemove",
      callback: (tipKey, clientX, clientY) => {
        let container = ganttContainer.value;
        if (!container) return;
        let bouding = container.getBoundingClientRect();
        let top = clientY - bouding.y;
        let left = clientX - bouding.x;

        tipStyle.value = {
          left: left + "px",
          top: top + "px",
        };
      },
    },
    {
      name: "mouseleave",
      callback: () => {
        tipValue.value = "";
        tipStyle.value = {};
      },
    },
  ];

  eventHub.batchOn(names);
}
</script>

<style >
* {
  box-sizing: border-box;
}
.container {
  position: relative;
  width: calc(100% - 200px);
  height: 600px;
  border: 1px solid orange;
  margin: 100px;
  display: flex;
}
.left-board {
  padding-top: 60px;
  width: 200px;
  height: 100%;
  border-right: 1px solid red;
  /* border: 1px solid cyan; */
  position: relative;
  overflow: hidden;
}
.right-board {
  flex: 1;
  /* border: 1px solid red; */
}
.svg-container {
  width: 100%;
  height: 100%;
  background-color: #eee;
}
.item-cell {
  box-sizing: border-box;
  width: 100%;
  background-color: #eee;
  border-bottom: 1px solid red;
  position: absolute;
  top: 0;
  left: 0;
  display: flex;
  align-items: center;
}
.project-top-left-corner {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 100;
  background-color: white;
  width: 100%;
  height: 60px;
}
.tool-tip {
  z-index: 2000;
  position: absolute;
  top: 0px;
  left: 0px;
  padding: 20px;
  border-radius: 10px;
  background-color: rgba(0, 0, 0, 0.8);
  color: white;
}
.header-title {
  font-size: 16px;
  font-weight: normal;
  transform: rotateZ(0deg);
  transform-origin: center;
  width: 40px;
  position: absolute;
  color: #666;
  text-shadow: -1px -1px 0 #fff, 1px -1px 0 #fff, -1px 1px 0 #fff,
    1px 1px 0 #fff; /* 文字描边 */
}
.progress-title {
  right: 30px;
  top: 8px;
}
.task-title {
  left: 30px;
  bottom: 10px;
}
.title-bg {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: SkyBlue;
}

.task-title-bg {
  background-color: #eee8aa;
  clip-path: polygon(0px 0px, 100% 100%, 0px 100%);
}
</style>